package com.jianbing.mongo;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.beanutils.BeanUtils;
import org.bson.Document;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jianbing.exception.ServiceException;

/**
 * Created with IntelliJ IDEA. User: LFL Date: 2017/4/24 Time: 14:46
 * Description:
 */

public class MongoHelper {

	public static final int ASC = 1; // 升序

	public static final int DESC = -1;// 降序

	/**
	 * 把实体bean对象转换成DBObject
	 *
	 * @param bean
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public static <T> Document bean2Document(T bean) throws ServiceException {

		if (bean == null) {
			return null;
		}
		Document dbObject = new Document();
		// 获取对象对应类中的所有属性域
		Field[] fields = bean.getClass().getDeclaredFields();
		Field[] superFields = bean.getClass().getSuperclass().getDeclaredFields();
		setFieldIntoDocument(fields, dbObject, bean);
		setFieldIntoDocument(superFields, dbObject, bean);

		return dbObject;
	}

	private static <T> void setFieldIntoDocument(Field[] fields, Document dbObject, T bean) throws ServiceException {
		if (fields == null || fields.length == 0 || dbObject == null || bean == null) {
			return;
		}
		try {
			for (Field field : fields) {
				// 获取属性名
				String varName = field.getName();
				if (varName.equals("_id")) {
					continue;
				}
				// 修改访问控制权限
				boolean accessFlag = field.isAccessible();
				if (!accessFlag) {
					field.setAccessible(true);
				}
				Object param = field.get(bean);
				if (param == null) {
					continue;
				} else if (param instanceof Integer) {// 判断变量的类型
					int value = ((Integer) param).intValue();
					dbObject.put(varName, value);
				} else if (param instanceof String) {
					String value = (String) param;
					dbObject.put(varName, value);
				} else if (param instanceof Double) {
					double value = ((Double) param).doubleValue();
					dbObject.put(varName, value);
				} else if (param instanceof Float) {
					float value = ((Float) param).floatValue();
					dbObject.put(varName, value);
				} else if (param instanceof Long) {
					long value = ((Long) param).longValue();
					dbObject.put(varName, value);
				} else if (param instanceof Boolean) {
					boolean value = ((Boolean) param).booleanValue();
					dbObject.put(varName, value);
				} else if (param instanceof Date) {
					Date value = (Date) param;
					dbObject.put(varName, value);
				} else if (param instanceof AtomicInteger) {
					dbObject.put(varName, ((AtomicInteger) param).get());
				} else if (param instanceof List<?>) {
					dbObject.put(varName, JSONArray.toJSONString(param));
				} else if (param instanceof Map) {
					dbObject.put(varName, JSONObject.toJSONString(param));
				}
				// 恢复访问控制权限
				field.setAccessible(accessFlag);
			}
		} catch (IllegalAccessException e) {
			throw new ServiceException(e);
		}
	}

	public static <T> T document2Bean(Document dbObject, Class<T> clazz) throws ServiceException {
		try {
			if (clazz == null || dbObject == null) {
				return null;
			}
			Field[] fields = clazz.getDeclaredFields();
			Field[] superFields = clazz.getSuperclass().getDeclaredFields();
			T bean = clazz.newInstance();
			setProperties(fields, dbObject, bean);
			setProperties(superFields, dbObject, bean);
			return bean;
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}

	public static <T> T document2Bean(Document dbObject, T bean) throws ServiceException {
		if (bean == null || dbObject == null) {
			return null;
		}
		Field[] fields = bean.getClass().getDeclaredFields();
		Field[] superFields = bean.getClass().getSuperclass().getDeclaredFields();
		setProperties(fields, dbObject, bean);
		setProperties(superFields, dbObject, bean);
		return bean;
	}

	private static <T> void setProperties(Field[] fields, Document dbObject, T bean) throws ServiceException {
		if (fields == null || fields.length == 0 || dbObject == null || bean == null) {
			return;
		}
		try {
			for (Field field : fields) {
				String varName = field.getName();
				Object object = dbObject.get(varName);
				if (object != null) {
					if (field.getType() == AtomicInteger.class) {
						object = new AtomicInteger(((Integer) object).intValue());
					} else if (field.getType() == List.class) {
						if (!(object instanceof List)) {
							object = (List<?>) JSONObject.parseArray((String) object);
						}
					} else if (field.getType() == Map.class) {
						if (!(object instanceof Map)) {
							object = (Map<?, ?>) JSONObject.parse((String) object);
						}

					}
					BeanUtils.setProperty(bean, varName, object);
				}
			}
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}
}